<template>
  <div class="cesium-draw">
    <div id="cesium-drawer"></div>
    <div class="mouse-postion">{{ nowPostion.wgs84 }}</div>
    <div class="tool-box">
      <!-- <div class="slider-box-wrapper"><slider-box v-model:value="terrainExaggeration" :max="2" /></div> -->
      <!-- <div class="slider-box-wrapper"><slider-box v-model:value="height" :max="100" :min="-100" :step="1" /></div> -->

      <div class="select-box-wrapper"><select-box :options="commonMaterials" /></div>
      <div class="select-box-wrapper"><select-box :options="baseMaterials" /></div>
      <div class="select-box-wrapper"><select-box :options="proceduralTextures" /></div>
      <div class="select-box-wrapper"><select-box :options="miscMaterials" /></div>
      <div class="select-box-wrapper"><select-box :options="compositeMaterials" /></div>
      <div class="select-box-wrapper"><select-box :options="polylineMaterials" /></div>

      <!-- <div class="select-box-wrapper"><a-checkbox v-model:checked="shadows">shadows</a-checkbox></div> -->
      <!-- <div class="select-box-wrapper"><a-checkbox v-model:checked="softShadows">soft shadows</a-checkbox></div> -->
      <!-- <div class="select-box-wrapper"><a-checkbox v-model:checked="terrainShadows">terrain shadows</a-checkbox></div> -->
      <!-- <div class="select-box-wrapper"><a-checkbox v-model:checked="picking">选择</a-checkbox></div> -->
      <div id="menu">
        <!-- <p><button @click="onClick('play')">播放</button></p> -->
        <!-- <p><button @click="onClick('stop')">暂停</button></p> -->
      </div>
    </div>
  </div>
</template>

<script>
import { DownOutlined, EditOutlined } from '@ant-design/icons-vue';
import { defineComponent, ref, watch } from 'vue';
import * as Cesium from '@cesium/Source/Cesium.js';
import MousePosition from '@functional/utils/mousePosition';
import selectBox from '@components/widgets/select-box';
import sliderBox from '@components/widgets/slider-box';

export default defineComponent({
  name: 'fabric', // 材质纹理
  components: { DownOutlined, EditOutlined, sliderBox, selectBox },
  setup() {
    return {
      viewer: null,
      synchronizer: null,
      isRepeating: true,
      videoOverlay: true
    };
  },
  data() {
    return {
      height: 0,
      setHeight: () => {},
      nowPostion: {},
      commonMaterials: [],
      baseMaterials: [],
      proceduralTextures: [],
      miscMaterials: [],
      compositeMaterials: [],
      polylineMaterials: []
    };
  },
  computed: {},
  watch: {
    height(val) {
      this.setHeight(val);
    }
  },
  mounted() {
    this.initViewer();
  },
  beforeUnmount() {
    if (this.viewer) {
      this.viewer.destroy();
      this.viewer = null;
    }
  },
  methods: {
    onViewerInited(viewer) {
      let vm = this;
      new MousePosition(viewer, pos => {
        vm.nowPostion = pos;
      });
    },

    initViewer() {
      let vm = this;
      Cesium.Ion.defaultAccessToken = $accessToken.default;
      let osm = new Cesium.ArcGisMapServerImageryProvider({
        // url: '//services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
        url: '//services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
      });
      var viewer = new Cesium.Viewer('cesium-drawer', {
        // imageryProvider: osm,
        contextOptions: {
          webgl: {
            alpha: true
          }
        },
        // shadows: true,
        animation: false,
        // baseLayerPicker: false,
        fullscreenButton: false,
        vrButton: false,
        homeButton: false,
        timeline: false,
        selectionIndicator: false,
        infoBox: false,
        // 注释时相当于使用默认地形，解开注释相当于使用全球地形
        // terrainProvider,
        shouldAnimate: true
      });

      //开启深度检测
      // viewer.scene.globe.depthTestAgainstTerrain = true;

      this.viewer = viewer;
      this.onViewerInited(viewer);
      this.initEffects();

      // this.viewer.flyTo(this.viewer.entities);
    },
    initEffects() {
      let vm = this;
      const viewer = this.viewer;
      var scene = viewer.scene;
      vm.createPrimitives(scene);
    },
    createPrimitives(scene) {
      let vm = this;
      var rectangle;
      var worldRectangle;
      var polyline;

      function applyAlphaMapMaterial(primitive, scene) {
        // Sandcastle.declare(applyAlphaMapMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            materials: {
              alphaMaterial: {
                type: 'AlphaMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_Color.jpg',
                  channel: 'r'
                }
              }
            },
            components: {
              diffuse: 'vec3(1.0)',
              alpha: 'alphaMaterial.alpha'
            }
          }
        });
      }

      function applyBumpMapMaterial(primitive, scene) {
        // Sandcastle.declare(applyBumpMapMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            materials: {
              diffuseMaterial: {
                type: 'DiffuseMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/bumpmap.png'
                }
              },
              bumpMaterial: {
                type: 'BumpMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/bumpmap.png',
                  strength: 0.8
                }
              }
            },
            components: {
              diffuse: 'diffuseMaterial.diffuse',
              specular: 0.01,
              normal: 'bumpMaterial.normal'
            }
          }
        });
      }

      function applyCheckerboardMaterial(primitive, scene) {
        // Sandcastle.declare(applyCheckerboardMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('Checkerboard');
      }

      function applyColorMaterial(primitive, scene) {
        // Sandcastle.declare(applyColorMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('Color');
      }

      function applyCompositeMaterial(primitive, scene) {
        // Sandcastle.declare(applyCompositeMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            uniforms: {
              image: '//zzgis.com/cdn/3d/Sandcastle/images/earthspec1k.jpg',
              heightField: '//zzgis.com/cdn/3d/Sandcastle/images/earthbump1k.jpg'
            },
            materials: {
              bumpMap: {
                type: 'BumpMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/earthbump1k.jpg'
                }
              }
            },
            source:
              'czm_material czm_getMaterial(czm_materialInput materialInput) { \n' +
              '    czm_material material = czm_getDefaultMaterial(materialInput); \n' +
              '    vec4 color; \n' +
              '    float heightValue = texture2D(heightField, materialInput.st).r; \n' +
              '    color.rgb = mix(vec3(0.2, 0.6, 0.2), vec3(1.0, 0.5, 0.2), heightValue); \n' +
              '    color.a = (1.0 - texture2D(image, materialInput.st).r) * 0.7; \n' +
              '    color = czm_gammaCorrect(color); \n' +
              '    material.diffuse = color.rgb; \n' +
              '    material.alpha = color.a; \n' +
              '    material.normal = bumpMap.normal; \n' +
              '    material.specular = step(0.1, heightValue); \n' + // Specular mountain tops
              '    material.shininess = 8.0; \n' + // Sharpen highlight
              '    return material; \n' +
              '} \n'
          }
        });
      }

      function applyDotMaterial(primitive, scene) {
        // Sandcastle.declare(applyDotMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('Dot');
      }

      function applyDiffuseMaterial(primitive, scene) {
        // Sandcastle.declare(applyDiffuseMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'DiffuseMap',
            uniforms: {
              image: '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_Color.jpg'
            }
          }
        });
      }

      function applyEmissionMapMaterial(primitive, scene) {
        // Sandcastle.declare(applyEmissionMapMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            materials: {
              diffuseMaterial: {
                type: 'DiffuseMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_Color.jpg'
                }
              },
              emissionMaterial: {
                type: 'EmissionMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/checkerboard.png',
                  repeat: {
                    x: 1,
                    y: 0.5
                  }
                }
              }
            },
            components: {
              diffuse: 'diffuseMaterial.diffuse',
              emission: 'emissionMaterial.emission * 0.2'
            }
          }
        });
      }

      function applyWaterMaterial(primitive, scene) {
        // Sandcastle.declare(applyWaterMaterial); // For highlighting in Sandcastle.

        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'Water',
            uniforms: {
              specularMap: '//zzgis.com/cdn/3d/Sandcastle/images/earthspec1k.jpg',
              normalMap: Cesium.buildModuleUrl('//zzgis.com/cdn/3d/Assets/Textures/waterNormals.jpg'),
              frequency: 10000.0,
              animationSpeed: 0.01,
              amplitude: 1.0
            }
          }
        });
      }

      function applyGridMaterial(primitive, scene) {
        // Sandcastle.declare(applyGridMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('Grid');
      }

      function applyImageMaterial(primitive, scene) {
        // Sandcastle.declare(applyImageMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'Image',
            uniforms: {
              image: '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_Color.jpg'
            }
          }
        });
      }

      function applyETC1SCompressedTextureMaterial(primitive, scene) {
        // Sandcastle.declare(applyETC1SCompressedTextureMaterial); // For highlighting in Sandcastle.

        var compressedImageUrl = '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_ETC1S.ktx2';

        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'Image',
            uniforms: {
              image: compressedImageUrl
            }
          }
        });
      }

      function applyUASTCCompressedTextureMaterial(primitive, scene) {
        // Sandcastle.declare(applyUASTCCompressedTextureMaterial); // For highlighting in Sandcastle.

        var compressedImageUrl = '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_UASTC.ktx2';

        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'Image',
            uniforms: {
              image: compressedImageUrl
            }
          }
        });
      }

      function applyNormalMapMaterial(primitive, scene) {
        // Sandcastle.declare(applyNormalMapMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            materials: {
              diffuseMaterial: {
                type: 'DiffuseMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/bumpmap.png'
                }
              },
              normalMap: {
                type: 'NormalMap',
                uniforms: {
                  image: '//zzgis.com/cdn/3d/Sandcastle/images/normalmap.png',
                  strength: 0.6
                }
              }
            },
            components: {
              diffuse: 'diffuseMaterial.diffuse',
              specular: 0.01,
              normal: 'normalMap.normal'
            }
          }
        });
      }

      function applySpecularMapMaterial(primitive, scene) {
        // Sandcastle.declare(applySpecularMapMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = new Cesium.Material({
          fabric: {
            type: 'SpecularMap',
            uniforms: {
              image: '//zzgis.com/cdn/3d/Sandcastle/images/Cesium_Logo_Color.jpg',
              channel: 'r'
            }
          }
        });
      }

      function applyStripeMaterial(primitive, scene) {
        // Sandcastle.declare(applyStripeMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('Stripe');
      }

      function applyRimLightingMaterial(primitive, scene) {
        // Sandcastle.declare(applyRimLightingMaterial); // For highlighting in Sandcastle.
        primitive.appearance.material = Cesium.Material.fromType('RimLighting');
      }

      function applyPolylineArrowMaterial(primitive, scene) {
        // Sandcastle.declare(applyPolylineArrowMaterial); // For highlighting in Sandcastle.
        var material = Cesium.Material.fromType('PolylineArrow');
        primitive.material = material;
      }

      function applyPolylineGlowMaterial(primitive, scene) {
        // Sandcastle.declare(applyPolylineGlowMaterial); // For highlighting in Sandcastle.
        var material = Cesium.Material.fromType('PolylineGlow', {
          color: Cesium.Color.CRIMSON,
          glowPower: 0.2,
          taperPower: 0.4
        });
        primitive.material = material;
      }

      function applyPolylineOutlineMaterial(primitive, scene) {
        // Sandcastle.declare(applyPolylineOutlineMaterial); // For highlighting in Sandcastle.
        var material = Cesium.Material.fromType('PolylineOutline', {
          outlineWidth: primitive.width / 2.0
        });
        primitive.material = material;
      }

      function createButtons(scene) {
        function toggleRectangleVisibility() {
          rectangle.show = true;
          worldRectangle.show = false;
          polyline.show = false;
        }

        function toggleWorldRectangleVisibility() {
          worldRectangle.show = true;
          rectangle.show = false;
          polyline.show = false;
        }

        function togglePolylineVisibility() {
          polyline.show = true;
          worldRectangle.show = false;
          rectangle.show = false;
        }

        vm.commonMaterials = [
          {
            text: 'Common materials'
          },
          {
            text: 'Color',
            onselect: function() {
              toggleRectangleVisibility();
              applyColorMaterial(rectangle, scene);
              // Sandcastle.highlight(applyColorMaterial);
            }
          },
          {
            text: 'Image',
            onselect: function() {
              toggleRectangleVisibility();
              applyImageMaterial(rectangle, scene);
              // Sandcastle.highlight(applyImageMaterial);
            }
          },
          {
            text: 'ETC1S Compressed Image',
            onselect: function() {
              if (!Cesium.FeatureDetection.supportsBasis(scene)) {
                window.alert('This browser does not support Basis Universal compressed textures');
              }
              toggleRectangleVisibility();
              applyETC1SCompressedTextureMaterial(rectangle, scene);
              // Sandcastle.highlight(applyETC1SCompressedTextureMaterial);
            }
          },
          {
            text: 'UASTC Compressed Image',
            onselect: function() {
              if (!Cesium.FeatureDetection.supportsBasis(scene)) {
                window.alert('This browser does not support Basis Universal compressed textures');
              }
              toggleRectangleVisibility();
              applyUASTCCompressedTextureMaterial(rectangle, scene);
              // Sandcastle.highlight(applyUASTCCompressedTextureMaterial);
            }
          }
        ];

        vm.proceduralTextures = [
          {
            text: 'Procedural textures'
          },
          {
            text: 'Checkerboard',
            onselect: function() {
              toggleRectangleVisibility();
              applyCheckerboardMaterial(rectangle, scene);
              // Sandcastle.highlight(applyCheckerboardMaterial);
            }
          },
          {
            text: 'Dot',
            onselect: function() {
              toggleRectangleVisibility();
              applyDotMaterial(rectangle, scene);
              // Sandcastle.highlight(applyDotMaterial);
            }
          },
          {
            text: 'Grid',
            onselect: function() {
              toggleRectangleVisibility(rectangle, worldRectangle);
              applyGridMaterial(rectangle, scene);
              // Sandcastle.highlight(applyGridMaterial);
            }
          },
          {
            text: 'Stripe',
            onselect: function() {
              toggleRectangleVisibility();
              applyStripeMaterial(rectangle, scene);
              // Sandcastle.highlight(applyStripeMaterial);
            }
          }
        ];

        vm.baseMaterials = [
          {
            text: 'Base materials'
          },
          {
            text: 'Alpha Map',
            onselect: function() {
              toggleRectangleVisibility();
              applyAlphaMapMaterial(rectangle, scene);
              // Sandcastle.highlight(applyAlphaMapMaterial);
            }
          },
          {
            text: 'Bump Map',
            onselect: function() {
              toggleRectangleVisibility();
              applyBumpMapMaterial(rectangle, scene);
              // Sandcastle.highlight(applyBumpMapMaterial);
            }
          },
          {
            text: 'Diffuse',
            onselect: function() {
              toggleRectangleVisibility();
              applyDiffuseMaterial(rectangle, scene);
              // Sandcastle.highlight(applyDiffuseMaterial);
            }
          },
          {
            text: 'Emission Map',
            onselect: function() {
              toggleRectangleVisibility();
              applyEmissionMapMaterial(rectangle, scene);
              // Sandcastle.highlight(applyEmissionMapMaterial);
            }
          },
          {
            text: 'Normal Map',
            onselect: function() {
              toggleRectangleVisibility();
              applyNormalMapMaterial(rectangle, scene);
              // Sandcastle.highlight(applyNormalMapMaterial);
            }
          },
          {
            text: 'Specular Map',
            onselect: function() {
              toggleRectangleVisibility();
              applySpecularMapMaterial(rectangle, scene);
              // Sandcastle.highlight(applySpecularMapMaterial);
            }
          }
        ];

        vm.miscMaterials = [
          {
            text: 'Misc materials'
          },
          {
            text: 'Rim Lighting',
            onselect: function() {
              toggleWorldRectangleVisibility();
              applyRimLightingMaterial(worldRectangle, scene);
              // Sandcastle.highlight(applyRimLightingMaterial);
            }
          },
          {
            text: 'Water',
            onselect: function() {
              toggleWorldRectangleVisibility();
              applyWaterMaterial(worldRectangle, scene);
              // Sandcastle.highlight(applyWaterMaterial);
            }
          }
        ];

        vm.compositeMaterials = [
          {
            text: 'Example composite materials'
          },
          {
            text: 'Composite Example',
            onselect: function() {
              toggleWorldRectangleVisibility();
              applyCompositeMaterial(worldRectangle, scene);
              // Sandcastle.highlight(applyCompositeMaterial);
            }
          }
        ];

        vm.polylineMaterials = [
          {
            text: 'Polyline materials'
          },
          {
            text: 'Polyline Arrow',
            onselect: function() {
              togglePolylineVisibility();
              applyPolylineArrowMaterial(polyline, scene);
              // Sandcastle.highlight(applyPolylineArrowMaterial);
            }
          },
          {
            text: 'Polyline Glow',
            onselect: function() {
              togglePolylineVisibility();
              applyPolylineGlowMaterial(polyline, scene);
              // Sandcastle.highlight(applyPolylineGlowMaterial);
            }
          },
          {
            text: 'Polyline Outline',
            onselect: function() {
              togglePolylineVisibility();
              applyPolylineOutlineMaterial(polyline, scene);
              // Sandcastle.highlight(applyPolylineOutlineMaterial);
            }
          }
        ];

        // document.getElementById('toolbar').style.width = '10%';
      }

      function createPrimitives(scene) {
        rectangle = scene.primitives.add(
          new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
              geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(-120.0, 20.0, -60.0, 40.0),
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
              })
            }),
            appearance: new Cesium.EllipsoidSurfaceAppearance({
              aboveGround: false
            })
          })
        );

        worldRectangle = scene.primitives.add(
          new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
              geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
              })
            }),
            appearance: new Cesium.EllipsoidSurfaceAppearance({
              aboveGround: false
            }),
            show: false
          })
        );

        var polylines = scene.primitives.add(new Cesium.PolylineCollection());
        polyline = polylines.add({
          positions: Cesium.PolylinePipeline.generateCartesianArc({
            positions: Cesium.Cartesian3.fromDegreesArray([-110.0, 42.0, -85.0, 36.0, -100.0, 25.0, -77.0, 12.0])
          }),
          width: 10.0,
          show: false
        });
      }

      createPrimitives(scene);
      createButtons(scene);
    },
    handleClick(value) {
      const viewer = this.viewer;
      switch (value) {
        case 'isRepeating':
          break;
      }
    }
  }
});
</script>

<style scoped lang="less">
.cesium-draw {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  color: white;
  font-size: 14px;

  #cesium-drawer {
    width: 100%;
    height: 100%;
    overflow: hidden;
    :deep(.cesium-viewer-bottom) {
      display: none !important;
    }
  }

  .mouse-postion {
    position: absolute;
    bottom: 10px;
    right: 10px;
    font-size: 14px;
    padding: 8px 12px;
    line-height: 16px;
    color: white;
    z-index: 9999;
    background-color: rgba(40, 48, 60, 1);
    border-radius: 3px;
    opacity: 0.8;
  }
}

.tool-box {
  position: absolute;
  top: 70px;
  left: 10px;
  z-index: 9;

  #menu {
    padding-top: 20px;
    button {
      background-color: rgba(0, 0, 0, 0.75);
      border-color: rgba(0, 0, 0, 0);
      cursor: pointer;
      transition: all 500ms;
      &:hover {
        opacity: 0.75;
      }
    }
  }

  .slider-box-wrapper {
    width: 18em;
    padding: 0 10px;
    background-color: rgba(0, 0, 0, 0.75);
    margin-bottom: 10px;
  }

  .select-box-wrapper {
    padding: 5px 15px;
    background-color: rgba(0, 0, 0, 0.75);
    margin-bottom: 10px;
    width: auto;
  }
}
</style>
